package com.oros.db;

import com.vaadin.data.Property;

public class AEColumnProperty implements Property {

	private static final long serialVersionUID = 1794677180449321979L;
	private boolean bIsReadOnly = false;
	private Object value,changedValue;
	private Class<?> type ;
	private boolean modified=false;
	private AERawItem parent;
	private AEFieldFormatter formatter;
	public int columnNo;
	public AEColumnProperty()
	{
		
	}
	public AEColumnProperty(AERawItem item,Object value,Class<?> type,AEFieldFormatter formatter,int columnNo)
	{
		parent = item;
		this.type = type;
		this.columnNo = columnNo;
		this.formatter = formatter;
		
		if (value!=null && value.getClass()!=type)
		{
		    value=conversion(type,value,false);
		}
		
		this.value = value;
		this.changedValue = value;
		
	}
	@Override
	public Object getValue() {
		//System.out.println("Get "+columnNo+" value:"+changedValue+" type:"+(changedValue==null?"--":changedValue.getClass().getCanonicalName()));
		return changedValue;
	}
    public static Object conversion(Class<?> type,Object newValue,boolean aerawitemTolerable)
    {
    	if (newValue instanceof AERawItem) 
		{
    		if (aerawitemTolerable) return newValue;
			long lvalue=((AERawItem)newValue).getIdKey();
			if (type==Integer.class)
			      newValue=new Integer((int)lvalue);
			else if (type==Long.class)
				      newValue=new Long(lvalue);
			else if (type==java.util.Date.class)
				      newValue=new java.util.Date(lvalue);
			else if (type==String.class)
				      newValue=Long.toString(lvalue);
		} else
    	if (type==Integer.class)
		{
			if (newValue instanceof Long)
			{
				newValue= new Integer(((Long)newValue).intValue());
			} else
			if (newValue instanceof java.util.Date)
			{
				newValue= new Integer((int)((java.util.Date)newValue).getTime());
			}
			else if (newValue instanceof Boolean)
			{
				newValue= new Integer(((Boolean)newValue).booleanValue()?1:0);
			}
			else
			{
				try
				{
					newValue = new Integer(Integer.parseInt(newValue.toString()));
				} catch(Exception e)
				{
					newValue = new Integer(0);
				}
			}
		} else if (type==Long.class)
		{
			if (newValue instanceof Integer)
			{
				newValue= new Long(((Integer)newValue).longValue());
			} else
			if (newValue instanceof java.util.Date)
			{
				newValue= new Long(((java.util.Date)newValue).getTime());
			}
			else if (newValue instanceof Boolean)
			{
				newValue= new Long(((Boolean)newValue).booleanValue()?1L:0L);
			}
			else
			{
				try
				{
					newValue = new Long(Long.parseLong(newValue.toString()));
				} catch(Exception e)
				{
					newValue = new Long(0L);
				}
			}
		} else if (type==String.class)
		{
			newValue= newValue.toString();
		}
		else if (type==java.util.Date.class)
		{
			if (newValue instanceof Long)
			{
				newValue = new java.util.Date(((Long)newValue).longValue());
			}
			else if (newValue instanceof Integer)
			{
				newValue = new java.util.Date(((Integer)newValue).longValue());
			}
			else 
			{
				try
				{
				   java.text.DateFormat df = java.text.DateFormat.getDateInstance();
				   newValue = df.parse(newValue.toString());
				}
				catch(Exception e)
				{
					newValue = new java.util.Date();
				}
			}
		}
		else if (type==Boolean.class)
		{
			String s = newValue.toString().trim().toUpperCase();
			if (s.length()==0) newValue=new Boolean(false);
			else
			{
				char c = s.charAt(0);
				if (c=='0' || c=='F' || c=='N') newValue = new Boolean(false);
				else newValue = new Boolean(true);
			}
		}
    	return newValue;
    }
	@Override
	public void setValue(Object newValue) throws ReadOnlyException,
			ConversionException {
		if (bIsReadOnly) throw new ReadOnlyException();
		//System.out.println(formatter+" setValue "+columnNo+" value:"+changedValue+" new: "+newValue+" type:"+(changedValue==null?"--":changedValue.getClass().getCanonicalName()));
		if (formatter!=null) newValue = formatter.setField(parent,this,newValue);
		if (newValue==null)
		{
			if (changedValue!=null)
			{
				changedValue=null;
				modified = true;
				if (parent!=null)
					parent.setModified(true);
			}
            return;				
		}
		if (newValue.getClass()!=type)
		{
			newValue = conversion(type,newValue,false);
		}
		if (!newValue.equals(changedValue))
		{
			changedValue = newValue;
			modified = true;
			if (parent!=null)
				parent.setModified(true);
		}
	}
    public void setUncheckedValue(Object newValue)
    {
    	if (newValue!=null && newValue.getClass()!=type)
    	{
    		newValue = conversion(type,newValue,true);
    	}
    	changedValue = newValue;
  	    value = changedValue;
  	    modified = false;
    }
	@Override
	public Class<?> getType() {
		return type;
	}

	@Override
	public boolean isReadOnly() {
		return bIsReadOnly;
	}
    @Override
    public String toString()
    {
    	return changedValue==null?"":changedValue.toString();
    }
    @Override
    public int hashCode()
    {
    	return changedValue==null?0:changedValue.hashCode();
    }
    @Override
    public boolean equals(Object o)
    {
       if (changedValue==null) return o==null;
       if (o==null) return false;
       return changedValue.equals(o);   
    }
	@Override
	public void setReadOnly(boolean newStatus) {
		bIsReadOnly= newStatus;
	}
    public void commit()
    {
    	if (modified)
    	{
    	  value = changedValue;
    	  modified = false;
    	}
    }
    public void rollback()
    {
    	changedValue = value;
    	modified = false;
    }
}
